﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Cms.Core.Data.Sql
{
    /// <summary>
    /// 数据相关扩展
    /// </summary>
    public static class DataExtensions
    {
        //从属性列表为DataTable创建列
        private static void CreateColumns(DataTable table, PropertyInfo[] piArr)
        {
            table.Columns.Clear();
            foreach (var pi in piArr)
            {
                table.Columns.Add(pi.Name, pi.PropertyType);
            }
        }

        //用obj的属性填充row
        private static void FillDataRow(DataRow row, object obj, PropertyInfo[] piArr)
        {
            foreach (var pi in piArr)
            {
                row[pi.Name] = pi.GetValue(obj);
            }
        }

        //用row的栏填充obj
        public static void FillObject<T>(T obj, DataRow row, PropertyInfo[] piArr)
        {
            foreach (var pi in piArr)
            {
                try
                {
                    pi.SetValue(obj, row[pi.Name]);
                }
                catch
                {
                }
            }
        }

        /// <summary>
        /// 从类型为DataTable创建Columns
        /// </summary>
        /// <param name="table">DataTable对象</param>
        /// <param name="type">作为创建模板的类型</param>
        public static void CreateColumsFromType(this DataTable table, Type type)
        {
            PropertyInfo[] piArr = type.GetProperties();
            CreateColumns(table, piArr);
        }

        /// <summary>
        /// 从object为DataTable创建Columns
        /// </summary>
        /// <param name="table">DataTable对象</param>
        /// <param name="obj">作为创建模板的object</param>
        public static void CreateColumsFromObject(this DataTable table, object obj)
        {
            CreateColumsFromType(table, obj.GetType());
        }

        /// <summary>
        /// 将DataRow转换为强类型
        /// </summary>
        /// <typeparam name="T">要转换为的强类型</typeparam>
        /// <param name="row">要转换的DataRow对象</param>
        /// <returns>转换后的强类型对象</returns>
        public static T ToObject<T>(this DataRow row)
        {
            if (row == null)
            {
                return default(T);
            }
            var obj = Activator.CreateInstance<T>();
            PropertyInfo[] piArr = typeof(T).GetProperties();
            FillObject(obj, row, piArr);
            return obj;
        }

        /// <summary>
        /// 将对象转换为DataRow对象
        /// </summary>
        /// <param name="obj">要转换的对象</param>
        /// <returns>转换后的DataRow对象</returns>
        public static DataRow ToDataRow(this object obj)
        {
            if (obj == null)
            {
                return null;
            }
            PropertyInfo[] piArr = obj.GetType().GetProperties();
            DataTable dt = new DataTable();
            CreateColumns(dt, piArr);

            DataRow row = dt.NewRow();
            FillDataRow(row, obj, piArr);

            return row;
        }

        /// <summary>
        /// 将对象转换为属于指定DataTable的DataRow对象
        /// </summary>
        /// <param name="table">属于的table</param>
        /// <param name="obj">要转换的对象</param>
        /// <returns>转换后的属于指定DataTable的DataRow对象</returns>
        public static DataRow ToDataRow(this object obj, DataTable table)
        {
            if (obj == null)
            {
                return null;
            }
            PropertyInfo[] piArr = obj.GetType().GetProperties();
            CreateColumns(table, piArr);

            DataRow row = table.NewRow();
            FillDataRow(row, obj, piArr);

            return row;
        }


        /// <summary>
        /// 将DataTable转换为IEnumerable的强类型对象
        /// </summary>
        /// <typeparam name="T">要转换为的强类型</typeparam>
        /// <param name="table">要转换的DataTable对象</param>
        /// <returns>转换后的IEnumerable的强类型对象</returns>
        //public static IEnumerable<T> ToEnumerable<T>(this DataTable table)
        //{
        //    List<T> list = new List<T>();
        //    PropertyInfo[] piArr = typeof(T).GetProperties();
        //    foreach (DataRow row in table.Rows)
        //    {
        //        var obj = Activator.CreateInstance<T>();
        //        FillObject(obj, row, piArr);
        //        list.Add(obj);
        //    }
        //    return list.AsEnumerable<T>();
        //}

        /// <summary>
        /// 将IEnumerable的强类型对象转换为DataTable
        /// </summary>
        /// <typeparam name="T">要转换的强类型</typeparam>
        /// <param name="objArr">要转换的IEnumerable的强类型对象</param>
        /// <returns>转换后的DataTable对象</returns>
        public static DataTable ToDataTable<T>(this IEnumerable<T> objArr)
        {
            DataTable dt = new DataTable();
            PropertyInfo[] piArr = typeof(T).GetProperties();
            CreateColumns(dt, piArr);

            foreach (var obj in objArr)
            {
                DataRow row = dt.NewRow();
                FillDataRow(row, obj, piArr);
                dt.Rows.Add(row);
            }
            return dt;
        }

        /// <summary>
        /// 将DataSet转换为IEnumerable的IEnumerable的强类型对象
        /// </summary>
        /// <typeparam name="T">要转换为的强类型</typeparam>
        /// <param name="set">要转换的DataSet对象</param>
        /// <returns>转换后的IEnumerable的IEnumerable的强类型对象</returns>
        public static IEnumerable<IEnumerable<T>> ToEnumerableEnumerable<T>(this DataSet set)
        {
            List<IEnumerable<T>> rsl = new List<IEnumerable<T>>();
            PropertyInfo[] piArr = typeof(T).GetProperties();

            foreach (DataTable dt in set.Tables)
            {
                List<T> list = new List<T>();
                foreach (DataRow row in dt.Rows)
                {
                    var obj = Activator.CreateInstance<T>();
                    FillObject(obj, row, piArr);
                    list.Add(obj);
                }
                rsl.Add(list.AsEnumerable<T>());
            }
            return rsl.AsEnumerable();
        }
    }
}
